package com.group01.community.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.group01.community.entity.SysMenu;
import com.group01.community.entity.SysRole;
import com.group01.community.entity.SysRoleMenu;
import com.group01.community.entity.vo.SysUserVo;
import com.group01.community.mapper.SysMenuMapper;
import com.group01.community.mapper.SysRoleMenuMapper;
import com.group01.community.mapper.SysUserMapper;
import com.group01.community.service.SysRoleMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.group01.community.utils.ResponseResult;
import com.group01.community.utils.StringUtils;
import org.apache.catalina.security.SecurityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色和菜单关联表 服务实现类
 * </p>
 *
 * @author guoyuan
 * @since 2025-05-01
 */
@Service
public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRoleMenu> implements SysRoleMenuService {

    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private SysMenuMapper sysMenuMapper;

    @Override
    public List<SysRoleMenu> getMenuIdsByRoldId(String roldId) {
        return sysRoleMenuMapper.getMenuIdsByRoldId(roldId);
    }

    @Override
    public List<SysMenu> getCurrentUserMenu() {
        String userName = SecurityContextHolder.getContext().getAuthentication().getName();
        if (StringUtils.isEmpty(userName)){
            throw new RuntimeException("用户不存在或未登录");
        }


        List<SysRole> userRole = sysUserMapper.queryRoleListByUserName(userName);
        // 随机取一个

        if (userRole == null || userRole.isEmpty()){
            throw new RuntimeException("当前用户没有分配角色，请分配后登录");
        }

        SysRole sysRole = userRole.get(0);

        List<SysRoleMenu> menuIdsByRoldId = this.getMenuIdsByRoldId(sysRole.getRoleId().toString());
        if (menuIdsByRoldId == null || menuIdsByRoldId.isEmpty()){
            throw new RuntimeException("当前用户没有分配菜单，请分配后登录");
        }

        List<Long> menuIds = menuIdsByRoldId.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());

        List<SysMenu> sysMenus = new ArrayList<>();
        if (!Objects.equals(userName, "admin")){
            QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("menu_id", menuIds);
            sysMenus = sysMenuMapper.selectList(queryWrapper);
            if (sysMenus == null || sysMenus.isEmpty()){
                throw new RuntimeException("当前用户没有分配菜单，请分配后登录");
            }

            List<Long> twoLevelMenuIds = sysMenus.stream().map(SysMenu::getParentId).collect(Collectors.toList());

            QueryWrapper<SysMenu> queryWrapper2 = new QueryWrapper<>();
            queryWrapper2.in("menu_id", twoLevelMenuIds);
            List<SysMenu> twoLevelMenus = sysMenuMapper.selectList(queryWrapper2);

            sysMenus.addAll(twoLevelMenus);

            // 查询一级菜单
            List<Long> oneLevelMenuIds = twoLevelMenus.stream().map(SysMenu::getParentId).collect(Collectors.toList());
            QueryWrapper<SysMenu> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.in("menu_id", oneLevelMenuIds);
            List<SysMenu> oneLevelMenus = sysMenuMapper.selectList(queryWrapper1);
            sysMenus.addAll(oneLevelMenus);

        } else {
            QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("menu_id", menuIds);

            sysMenus = sysMenuMapper.selectList(queryWrapper);
        }

        // 获取所有父级菜单
        List<SysMenu> parentMenus = sysMenus.stream().filter(sysMenu -> sysMenu.getParentId().equals(0L)).collect(Collectors.toList());
        // 递归查询子菜单
        List<SysMenu> resultMenus = new ArrayList<>();
        for (SysMenu sysMenu : parentMenus) {
            List<SysMenu> children = this.getChildren(sysMenu, sysMenus);

            children.sort(Comparator.comparingInt(SysMenu::getOrderNum));

            sysMenu.setChildren(children);

            Map<String, Object> meta = new HashMap<>();
            meta.put("title", sysMenu.getMenuName());
            meta.put("icon", sysMenu.getIcon());
            sysMenu.setMeta(meta);

            resultMenus.add(sysMenu);
        }

        // 根据sort 字段进行排序
        resultMenus.sort(Comparator.comparingInt(SysMenu::getOrderNum));

        // 排除掉按钮
        for (Iterator<SysMenu> iterator = resultMenus.iterator(); iterator.hasNext();) {
            SysMenu nextMenu = iterator.next();
            if (nextMenu.getMenuType().equals("F")) {
                iterator.remove();
            }
            this.filterStateF(nextMenu);
        }

        //根据menuId去重
        Set<SysMenu> menuSets = new HashSet<>(resultMenus);
        resultMenus = new ArrayList<>(menuSets);

        // 对子元素去重
        for (SysMenu resultMenu : resultMenus) {
            if (resultMenu.getChildren() == null || resultMenu.getChildren().isEmpty()){
                continue;
            }
            Set<SysMenu> childMenuSets = new HashSet<>(resultMenu.getChildren());
            List<SysMenu> childMenus = new ArrayList<>(childMenuSets);
            resultMenu.setChildren(childMenus);
        }

        return resultMenus;
    }

    private void filterStateF(SysMenu nextMenu){
        if (nextMenu.getChildren() == null){
            return;
        }

        for (SysMenu child : nextMenu.getChildren()) {
            if (child.getMenuType().equals("F")) {
                nextMenu.setChildren(Collections.EMPTY_LIST);
            }
            this.filterStateF(child);
        }
    }

    private List<SysMenu> getChildren(SysMenu sysMenu, List<SysMenu> sysMenus) {
        List<SysMenu> children = sysMenus.stream().filter(menu -> menu.getParentId().equals(sysMenu.getMenuId())).collect(Collectors.toList());
        for (SysMenu child : children) {

            Map<String, Object> meta = new HashMap<>();
            meta.put("title", child.getMenuName());
            meta.put("icon", child.getIcon());
            child.setMeta(meta);

            List<SysMenu> grandChildren = this.getChildren(child, sysMenus);
            child.setChildren(grandChildren);
        }
        return children;
   }
}
